package p.ithorns.tools.translator.sdk.handler;

import com.google.auto.service.AutoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import p.ithorns.tools.translator.annotation.Translator;
import p.ithorns.tools.translator.annotation.field.ModelField;
import p.ithorns.tools.translator.sdk.exception.DictFieldException;
import p.ithorns.tools.translator.sdk.provider.DictModelProvider;
import p.ithorns.tools.translator.sdk.utils.MD5Codec;
import p.ithorns.tools.translator.sdk.utils.ReflectUtil;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * ModelTranslator
 * <p>
 * Model转换
 * 实现Java Model 1:N 解释: 通过字典字段获取Model,解释当前对象下的多个字段。
 * 例如：在Order下通过userId, 获取User，填充Order下的userName,userAddress,userPhone等多个字段。
 * 需要提供者实现DictModelProvider
 *
 * @author Ht.L
 * @date 2025-02-05 22:28
 * @since 1.0.0
 */
@AutoService(Translator.class)
public class ModelTranslator implements Translator<Serializable, ModelField> {

    private static final Logger log = LoggerFactory.getLogger(ModelTranslator.class);

    private final ApplicationContext appCtx;

    public ModelTranslator(ApplicationContext appCtx) {
        this.appCtx = appCtx;
    }

    @Override
    @SuppressWarnings("unchecked")
    public String translate(ModelField annotation, Serializable key) {
        String beanName = annotation.bean();
        try {
            DictModelProvider<Serializable, Object> bean = appCtx.getBean(beanName, DictModelProvider.class);
            Object model = bean.getModel(key);
            return ReflectUtil.invokeReadMethod(model, annotation.prop());
        } catch (NoSuchBeanDefinitionException e) {
            String msg = String.format("@ModelField: No such bean: [%s]", beanName);
            throw new DictFieldException(msg, e);
        } catch (Exception e) {
            String msg = String.format("@ModelField: Failed to invoke #getDict on bean: [%s]", beanName);
            throw new DictFieldException(msg, e);
        }
    }

    @Override
    public Map<Serializable, Object> translate(ModelField annotation, Set<Serializable> ids) {
        String beanName = annotation.bean();
        String prop = annotation.prop();
        try {
            DictModelProvider<Serializable, Object> bean = appCtx.getBean(beanName, DictModelProvider.class);
            Map<Serializable, Object> models = bean.getModelMap(ids);
            Map<Serializable, Object> result = new HashMap<>();
            Set<Map.Entry<Serializable, Object>> entries = models.entrySet();
            for (Map.Entry<Serializable, Object> entry : entries) {
                Serializable id = entry.getKey();
                Object model = entry.getValue();
                result.put(id, ReflectUtil.invokeReadMethod(model, prop));
            }

            return result;
        } catch (NoSuchBeanDefinitionException e) {
            String msg = String.format("@ModelField: No such bean: [%s]", beanName);
            throw new DictFieldException(msg, e);
        } catch (Exception e) {
            String msg = String.format("@ModelField: Failed to invoke #getDictMap on bean: [%s]",beanName);
            throw new DictFieldException(msg, e);
        }
    }

    private String compress(Set<Serializable> keys) {
        TreeSet<Serializable> orderedKeys = new TreeSet<>(keys);
        // 拼接key后获取摘要
        String collect = orderedKeys.stream()
                .map(Object::toString)
                .collect(Collectors.joining(","));
        try {
            return MD5Codec.md5(collect);
        } catch ( Exception e) {
            log.error(e.getMessage());
            return collect;
        }
    }

}